/**
 * 额度检查工具类
 * 统一管理各种额度检查和跳转逻辑
 */

import { utils, userAPI, contactViewAPI } from './api.js'

/**
 * 额度类型枚举
 */
const CREDIT_TYPES = {
  PUBLISHING: 'publishing',      // 发布信息额度
  CHAT: 'chat',                 // 聊天消息额度
  CONTACT_VIEW: 'contact_view',  // 查看联系方式额度
  LOCAL_SERVICE: 'local_service' // 本地服务发布额度
}

/**
 * 套餐类型映射
 */
const PACKAGE_TYPE_MAP = {
  [CREDIT_TYPES.PUBLISHING]: 'paid',
  [CREDIT_TYPES.CHAT]: 'chat_message',
  [CREDIT_TYPES.CONTACT_VIEW]: 'contact_view',
  [CREDIT_TYPES.LOCAL_SERVICE]: 'local_service'
}

/**
 * 额度字段映射
 */
const CREDIT_FIELD_MAP = {
  [CREDIT_TYPES.PUBLISHING]: 'publishing_credits',
  [CREDIT_TYPES.CHAT]: 'chat_credits',
  [CREDIT_TYPES.CONTACT_VIEW]: 'contact_view_credits',
  [CREDIT_TYPES.LOCAL_SERVICE]: 'local_service_credits'  // 本地服务发布使用独立信用
}

const CHAT_CONFIG_CACHE_TTL = 60 * 1000;
const chatConfigState = {
  mode: 'paid',
  freeLimit: 3,
  lastFetchedAt: 0,
  initialized: false,
  loadingPromise: null
};

const normalizeChatConfig = (config = {}) => {
  const rawMode = typeof config.chat_message_mode === 'string'
    ? config.chat_message_mode.toLowerCase()
    : '';
  const rawLimit = config.chat_free_daily_limit ?? '0';
  const parsedLimit = parseInt(rawLimit, 10);
  return {
    mode: rawMode === 'free' ? 'free' : 'paid',
    freeLimit: Number.isNaN(parsedLimit) ? 0 : Math.max(0, parsedLimit)
  };
};

const fetchChatConfig = async () => {
  try {
    const response = await contactViewAPI.getConfig();
    if (response?.success && response.data) {
      const normalized = normalizeChatConfig(response.data);
      chatConfigState.mode = normalized.mode;
      chatConfigState.freeLimit = normalized.freeLimit;
      console.log(
        `[CreditChecker] 聊天配置更新完成: mode=${chatConfigState.mode}, freeLimit=${chatConfigState.freeLimit}`
      );
    } else {
      console.warn('[CreditChecker] 获取聊天配置失败:', response?.message);
    }
  } catch (error) {
    console.error('[CreditChecker] 获取聊天配置发生错误:', error);
  } finally {
    chatConfigState.initialized = true;
    chatConfigState.lastFetchedAt = Date.now();
  }
  return chatConfigState;
};

const ensureChatConfig = async (force = false) => {
  const now = Date.now();
  const needsRefresh =
    force ||
    !chatConfigState.initialized ||
    now - chatConfigState.lastFetchedAt > CHAT_CONFIG_CACHE_TTL;

  if (!needsRefresh) {
    return chatConfigState;
  }

  if (!chatConfigState.loadingPromise) {
    chatConfigState.loadingPromise = fetchChatConfig().finally(() => {
      chatConfigState.loadingPromise = null;
    });
  }

  return chatConfigState.loadingPromise;
};

/**
 * 额度检查器类
 */
class CreditChecker {

  // 静态属性，暴露额度类型枚举
  static CREDIT_TYPES = CREDIT_TYPES
  
  /**
   * 检查用户是否有足够的额度
   * @param {string} creditType 额度类型
   * @param {number} requiredAmount 需要的额度数量，默认为1
   * @returns {Promise<{hasCredit: boolean, currentCredit: number, message: string}>}
   */
  static async checkCredit(creditType, requiredAmount = 1) {
    try {
      // 检查登录状态
      if (!utils.isLoggedIn()) {
        return {
          hasCredit: false,
          currentCredit: 0,
          message: '请先登录'
        }
      }

      // 强制从服务器获取最新的用户信息，增加重试机制
      let userInfo
      const maxRetries = 3
      let retries = 0
      
      while (retries < maxRetries) {
        try {
          const response = await userAPI.getCurrentUser()
          if (response.success) {
            userInfo = response.data
            // 更新本地存储的用户信息
            uni.setStorageSync('userInfo', userInfo)
            break // 成功获取，跳出重试循环
          } else {
            console.warn(`获取用户信息失败，第${retries + 1}次重试:`, response.message)
            retries++
          }
        } catch (error) {
          console.warn(`从服务器获取用户信息失败，第${retries + 1}次重试:`, error.message)
          retries++
          
          // 如果不是最后一次重试，等待一小段时间再重试
          if (retries < maxRetries) {
            await new Promise(resolve => setTimeout(resolve, 500))
          }
        }
      }

      // 如果重试仍然失败，使用本地存储的信息作为最后手段
      if (!userInfo) {
        console.error('服务器获取用户信息完全失败，使用本地缓存数据')
        userInfo = utils.getCurrentUser()
        
        // 如果本地也没有数据，直接返回失败
        if (!userInfo) {
          return {
            hasCredit: false,
            currentCredit: 0,
            message: '无法获取用户信息，请重新登录'
          }
        }
        
        // 使用本地数据时，给出警告提示
        console.warn('使用本地缓存的用户信息，可能不是最新数据')
      }

      // 获取对应的额度字段
      const creditField = CREDIT_FIELD_MAP[creditType]
      if (!creditField) {
        return {
          hasCredit: false,
          currentCredit: 0,
          message: '无效的额度类型'
        }
      }

      const currentCredit = userInfo[creditField] || 0
      const hasCredit = currentCredit >= requiredAmount

      // 如果额度检查失败，再次强制刷新用户信息进行二次确认
      if (!hasCredit) {
        console.log('初次额度检查失败，进行二次确认...')
        try {
          const reconfirmResponse = await userAPI.getCurrentUser()
          if (reconfirmResponse.success) {
            const latestUserInfo = reconfirmResponse.data
            uni.setStorageSync('userInfo', latestUserInfo)
            const latestCredit = latestUserInfo[creditField] || 0
            
            console.log(`二次确认额度: ${latestCredit}, 需要: ${requiredAmount}`)
            
            if (latestCredit >= requiredAmount) {
              return {
                hasCredit: true,
                currentCredit: latestCredit,
                message: '额度充足'
              }
            }
          }
        } catch (reconfirmError) {
          console.error('二次确认额度失败:', reconfirmError)
        }
      }

      return {
        hasCredit,
        currentCredit,
        message: hasCredit ? '额度充足' : `${this.getCreditTypeName(creditType)}额度不足`
      }
    } catch (error) {
      console.error('检查额度失败:', error)
      return {
        hasCredit: false,
        currentCredit: 0,
        message: '检查额度失败'
      }
    }
  }

  /**
   * 检查额度并处理不足的情况
   * @param {string} creditType 额度类型
   * @param {number} requiredAmount 需要的额度数量，默认为1
   * @param {Object} options 选项
   * @param {string} options.fromPage 来源页面路径，用于购买后返回
   * @param {string} options.action 操作描述，用于提示信息
   * @returns {Promise<boolean>} 是否有足够额度
   */
  static async checkAndHandle(creditType, requiredAmount = 1, options = {}) {
    const { fromPage, action } = options
    
    const result = await this.checkCredit(creditType, requiredAmount)
    
    if (!result.hasCredit) {
      // 如果是登录问题，直接跳转到登录页
      if (result.message === '请先登录') {
        uni.showToast({
          title: result.message,
          icon: 'none'
        })
        setTimeout(() => {
          uni.navigateTo({
            url: '/pages/login/login'
          })
        }, 1500)
        return false
      }

      // 额度不足，显示确认对话框
      const actionText = action || this.getDefaultActionText(creditType)
      const creditTypeName = this.getCreditTypeName(creditType)
      
      // 构建更详细的提示内容
      let content = `您当前有${result.currentCredit}个${creditTypeName}额度，但需要${requiredAmount}个才能完成此操作`
      if (requiredAmount > 1) {
        content += `\n\n注意：全国总群发送需要向所有群组发送消息，消耗额度较多`
      }
      content += `\n\n是否前往购买更多额度？`
      
      return new Promise((resolve) => {
        uni.showModal({
          title: `${creditTypeName}额度不足`,
          content: content,
          confirmText: '去购买',
          cancelText: '取消',
          success: (res) => {
            if (res.confirm) {
              this.navigateToPackages(creditType, fromPage)
            }
            resolve(false)
          }
        })
      })
    }

    return true
  }

  /**
   * 跳转到套餐购买页面
   * @param {string} creditType 额度类型
   * @param {string} fromPage 来源页面路径
   */
  static navigateToPackages(creditType, fromPage) {
    const packageType = PACKAGE_TYPE_MAP[creditType]
    let url = '/pages/packages/packages'
    
    // 构建查询参数
    const params = []
    if (packageType) {
      params.push(`type=${packageType}`)
    }
    if (fromPage) {
      params.push(`from=${encodeURIComponent(fromPage)}`)
    }
    
    if (params.length > 0) {
      url += '?' + params.join('&')
    }
    
    uni.navigateTo({ url })
  }

  /**
   * 获取额度类型的中文名称
   * @param {string} creditType 额度类型
   * @returns {string}
   */
  static getCreditTypeName(creditType) {
    const nameMap = {
      [CREDIT_TYPES.PUBLISHING]: '发布信息',
      [CREDIT_TYPES.CHAT]: '聊天消息',
      [CREDIT_TYPES.CONTACT_VIEW]: '查看联系方式',
      [CREDIT_TYPES.LOCAL_SERVICE]: '本地服务发布'
    }
    return nameMap[creditType] || '未知'
  }

  /**
   * 获取默认的操作描述文本
   * @param {string} creditType 额度类型
   * @returns {string}
   */
  static getDefaultActionText(creditType) {
    const actionMap = {
      [CREDIT_TYPES.PUBLISHING]: '发布信息',
      [CREDIT_TYPES.CHAT]: '发送消息',
      [CREDIT_TYPES.CONTACT_VIEW]: '查看联系方式',
      [CREDIT_TYPES.LOCAL_SERVICE]: '发布本地服务'
    }
    return actionMap[creditType] || '进行此操作'
  }

  /**
   * 检查发布信息额度
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  static async checkPublishingCredit(options = {}) {
    return this.checkAndHandle(CREDIT_TYPES.PUBLISHING, 1, {
      fromPage: '/pages/listings/publish',
      action: '发布信息',
      ...options
    })
  }

  /**
   * 检查聊天消息额度
   * @param {number} requiredAmount 需要的额度数量
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  static async checkChatCredit(requiredAmount = 1, options = {}) {
    const config = await ensureChatConfig();
    if (config.mode === 'free') {
      console.log('[CreditChecker] 当前为免费聊天模式，跳过额度检查');
      return true;
    }

    return this.checkAndHandle(CREDIT_TYPES.CHAT, requiredAmount, {
      fromPage: '/pages/chat/chat',
      action: '发送消息',
      ...options
    })
  }

  /**
   * 返回当前聊天配置（会自动刷新缓存）
   * @param {boolean} force 是否强制刷新
   * @returns {Promise<{mode: string, freeLimit: number}>}
   */
  static async getChatConfig(force = false) {
    return ensureChatConfig(force)
  }

  /**
   * 判断是否为聊天免费模式（读取缓存，不强制刷新）
   * @returns {boolean}
   */
  static isChatFreeMode() {
    return chatConfigState.mode === 'free'
  }

  /**
   * 判断本次发送是否需要消耗聊天额度（会自动刷新配置）
   * @returns {Promise<boolean>}
   */
  static async shouldConsumeChatCredits() {
    const config = await ensureChatConfig()
    return config.mode !== 'free'
  }

  /**
   * 检查查看联系方式额度(私聊页面专用,始终检查额度)
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  static async checkContactViewCredit(options = {}) {
    return this.checkAndHandle(CREDIT_TYPES.CONTACT_VIEW, 1, {
      action: '查看联系方式',
      ...options
    })
  }

  /**
   * 检查查看联系方式额度(根据配置决定是否收费)
   * 用于公司库等需要根据配置控制收费的场景
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  static async checkContactViewCreditWithConfig(options = {}) {
    try {
      // 先检查后端配置是否启用收费功能
      console.log('开始检查联系方式查看配置...')
      const configResponse = await contactViewAPI.getConfig()
      console.log('配置API响应:', JSON.stringify(configResponse))

      if (configResponse.success) {
        const enableFee = configResponse.data.enable_contact_view_fee
        console.log('enable_contact_view_fee 值:', enableFee, '类型:', typeof enableFee)

        if (enableFee === '0') {
          // 未启用收费,直接返回 true,不检查额度
          console.log('✅ 联系方式查看收费功能未启用,免费查看')
          return true
        } else {
          console.log('⚠️ 联系方式查看收费功能已启用,需要检查额度')
        }
      } else {
        console.error('配置API返回失败:', configResponse.message)
      }
    } catch (error) {
      console.error('获取联系方式查看配置失败:', error)
      // 获取配置失败时,为了不影响用户体验,默认允许查看
      console.warn('无法获取配置,默认允许查看联系方式')
      return true
    }

    // 已启用收费,继续原有的额度检查逻辑
    console.log('继续执行额度检查逻辑...')
    return this.checkAndHandle(CREDIT_TYPES.CONTACT_VIEW, 1, {
      action: '查看联系方式',
      ...options
    })
  }

  /**
   * 检查本地服务发布额度
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  static async checkLocalServiceCredit(options = {}) {
    return this.checkAndHandle(CREDIT_TYPES.LOCAL_SERVICE, 1, {
      fromPage: '/pages/local-services/publish',
      action: '发布本地服务',
      ...options
    })
  }

  /**
   * 更新本地用户信息中的额度
   * @param {string} creditType 额度类型
   * @param {number} amount 变更数量（正数为增加，负数为减少）
   */
  static updateLocalCredit(creditType, amount) {
    try {
      const userInfo = utils.getCurrentUser()
      if (!userInfo) {
        console.warn('无法获取用户信息，跳过本地额度更新')
        return
      }

      const creditField = CREDIT_FIELD_MAP[creditType]
      if (!creditField) {
        console.warn('无效的额度类型:', creditType)
        return
      }

      const oldCredit = userInfo[creditField] || 0
      const newCredit = Math.max(0, oldCredit + amount)
      userInfo[creditField] = newCredit
      
      console.log(`本地额度更新: ${creditField} ${oldCredit} → ${newCredit} (变更: ${amount > 0 ? '+' : ''}${amount})`)
      
      uni.setStorageSync('userInfo', userInfo)
    } catch (error) {
      console.error('更新本地额度失败:', error)
    }
  }

  /**
   * 减少本地额度
   * @param {string} creditType 额度类型
   * @param {number} amount 减少数量
   */
  static reduceLocalCredit(creditType, amount = 1) {
    this.updateLocalCredit(creditType, -amount)
  }

  /**
   * 增加本地额度
   * @param {string} creditType 额度类型
   * @param {number} amount 增加数量
   */
  static addLocalCredit(creditType, amount = 1) {
    this.updateLocalCredit(creditType, amount)
  }
}

export default CreditChecker
